﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Runtime.InteropServices;
using System.Security.Principal;

namespace InfiniTec.DirectoryServices
{
    public class DomainTrustCollection
    {
        public static IEnumerable<DomainTrust> EnumerateDomainTrusts()
        {
            return EnumerateDomainTrusts(TrustFlags.All);
        }

        public static IEnumerable<DomainTrust> EnumerateDomainTrusts(TrustFlags flags)
        {
            return EnumerateDomainTrusts(null, flags);
        }

        public static IEnumerable<DomainTrust> EnumerateDomainTrusts(string serverName)
        {
            return EnumerateDomainTrusts(serverName, TrustFlags.All);
        }

        public static IEnumerable<DomainTrust> EnumerateDomainTrusts(string serverName, TrustFlags flags)
        {
            IntPtr trustptr;

            int trustCount;
            int result = SafeNativeMethods.DsEnumerateDomainTrusts(serverName, flags, out trustptr, out trustCount);

            if (result != 0)
            {
                throw new Win32Exception(result);
            }
            SafeNativeMethods.DS_DOMAINTRUST_ENTRY entry;
            try
            {
                IntPtr ptr = trustptr;
                for (int i = 0; i < trustCount; i++)
                {
                    entry = new SafeNativeMethods.DS_DOMAINTRUST_ENTRY();
                    Marshal.PtrToStructure(ptr, entry);
                    
                    DomainTrust trust = new DomainTrust();
                    trust.Name = Marshal.PtrToStringAuto(entry.DnsDomainName);
                    trust.NetBiosName = Marshal.PtrToStringAuto(entry.NetbiosDomainName);
                    trust.Flags = entry.Flags;
                    trust.Attributes = entry.TrustAttributes;
                    trust.DomainGuid = entry.DomainGuid;
                    trust.DomainSecurityIdentifier = new SecurityIdentifier(entry.DomainSid);

                    yield return trust;

                    ptr = (IntPtr) ((long) ptr + Marshal.SizeOf(typeof (SafeNativeMethods.DS_DOMAINTRUST_ENTRY)));
                }
            }
            finally
            {
                SafeNativeMethods.NetApiBufferFree(trustptr);
            }
        }
    }
}
